2-3 官方方案进阶:多环境配置读取
多环境配置
利用 envFilePath 配合 NODE_ENV,可以在不同启动命令下使用不同的配置文件。
安装 cross-env:
npm install cross-env
bash
创建环境配置文件:
.env.development:
DATABASE=mysql_dev
DATABASE_PASSWORD=test123
bash
.env.production:
DATABASE=mysql_prd
DATABASE_PASSWORD=test123321
bash
在 app.module.ts 中根据 NODE_ENV 动态加载:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
const envPath = `.env.${process.env.NODE_ENV || 'development'}`;
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath: envPath,
}),
],
})
export class AppModule {}
typescript
配置脚本:
{
"start:dev": "cross-env NODE_ENV=development nest start --watch",
"start:prod": "cross-env NODE_ENV=production node dist/main"
}
json
启动后,不同环境会自动加载对应的 .env 文件。
加载公共配置(load 方法)
当有大量配置项需要在 development 和 production 中共用时,可以创建一个公共的 .env 文件,通过 load 方法加载。
安装 dotenv:
pnpm install dotenv
bash
创建公共 .env 文件:
DB_URL=www.imooc.com
bash
在 app.module.ts 中使用 load 加载:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import * as dotenv from 'dotenv';
const envFilePath = `.env.${process.env.NODE_ENV || 'development'}`;
@Module({
imports: [
ConfigModule.forRoot({
isGlobal: true,
envFilePath,
load: [() => dotenv.config({ path: '.env' })],
}),
],
})
export class AppModule {}
typescript
优先级规则: 环境配置文件(如 .env.development)中的同名变量会覆盖公共 .env 文件中的值。
解析 YAML 格式配置
除了 .env 格式,还可以使用 js-yaml 解析 YAML 格式的配置文件。
安装依赖:
npm install js-yaml
npm install -D @types/js-yaml
bash
创建 config.yml:
http:
host: 'localhost'
port: 8080
db:
postgres:
url: 'localhost'
port: 5432
database: 'yaml-db'
sqlite:
database: 'sqlite.db'
yaml
创建配置加载文件 src/config/configuration.ts:
import { readFileSync } from 'fs';
import * as yaml from 'js-yaml';
import { join } from 'path';
const YAML_CONFIG_FILENAME = 'config.yml';
export default () => {
return yaml.load(readFileSync(join(__dirname, YAML_CONFIG_FILENAME), 'utf8'));
};
typescript
在 forRoot 中通过 load 方法加载:
import { Module } from '@nestjs/common';
import { ConfigModule } from '@nestjs/config';
import configuration from './config/configuration';
@Module({
imports: [
ConfigModule.forRoot({
load: [configuration],
}),
],
})
export class AppModule {}
typescript
定义类型接口并使用:
// src/interface.ts
export interface DatabaseConfig {
postgres: PostgresConfig;
sqlite: SqliteConfig;
}
// app.controller.ts
const db = this.configService.get<DatabaseConfig>('db');
// db.postgres.url, db.sqlite.database 等属性均可直接访问
typescript
envFilePath 接收数组
envFilePath 可以接收一个数组,靠前的文件具有更高的优先级:
ConfigModule.forRoot({
isGlobal: true,
envFilePath: [envPath, '.env'], // 环境文件优先,公共文件在后
})
typescript
这样即使使用 Joi 校验,也能对公共 .env 文件中的配置生效。
↑